# -*- coding: utf-8 -*-
"""
Created on Wed Oct  5 19:11:54 2016

@author: zxj
"""
'''
解读LineReceiver协议类
'''
class LineReceiver(protocol.Protocol, _PauseableMixin):
    """
    A protocol that receives lines and/or raw data, depending on mode.
    该协议是这样的,根据模式来接受一行数据还是原始数据
    In line mode, each line that's received becomes a callback to
    L{lineReceived}.  In raw data mode, each chunk of raw data becomes a
    callback to L{LineReceiver.rawDataReceived}.
    The L{setLineMode} and L{setRawMode} methods switch between the two modes.

    This is useful for line-oriented protocols such as IRC, HTTP, POP, etc.
    在行模式中,每当一行数据被接受到的时候,lineReceived就会被回调。
    在原始数据模式中,每一块原始数据将被LineReceiver.rawDataReceived回调
    @cvar delimiter: The line-ending delimiter to use. By default this is
                     C{b'\\r\\n'}.
    delimiter为行分割符号,默认是\r\n
    @cvar MAX_LENGTH: The maximum length of a line to allow (If a
                      sent line is longer than this, the connection is dropped).
                      Default is 16384.
    允许的最大的行的长度,超过这个长度,连接将会被断开
    """
    line_mode = 1
    _buffer = b''
    _busyReceiving = False
    delimiter = b'\r\n'
    MAX_LENGTH = 16384

    def clearLineBuffer(self):
        """
        Clear buffered data.

        @return: All of the cleared buffered data.
        @rtype: C{bytes}
        """
        b, self._buffer = self._buffer, b""  #分别赋值，清空缓冲区的数据，将缓冲区的数据返回
        return b


    def dataReceived(self, data):
        """
        Protocol.dataReceived.
        Translates bytes into lines, and calls lineReceived (or
        rawDataReceived, depending on mode.)
        传过来的数据是字节类型,二进制的,此处dataReceived就开始发挥它的作用
        将低层的数据流转换为高层的协议规定的格式化消息
        个人感觉：'是不是因为异步I/O事件驱动的？网络的不稳定性导致,数据的接受存在不确定性，也就是说数据的接受存在间断性，而不是连续的接受完。
        因此dataReceived可能会由于事件并发的触发而被被并发调用,可能在前一个接受的数据正在处理的同时，
        新的的数据被接受到。这些数据被存储在公共的缓冲区可以很好解决。
        """
        if self._busyReceiving:
            self._buffer += data   #为公共缓冲区，因为data接受具有不确定性，在接受一个data还正在进行处理，此时处于忙碌状态
                                    #又接受新的一个数据，附加到缓冲区。
            return

        try:
            self._busyReceiving = True
            self._buffer += data
            while self._buffer and not self.paused:  #对缓冲区'轮询',直到为空。
                if self.line_mode:
                    try:
                        line, self._buffer = self._buffer.split(
                            self.delimiter, 1)#取出一行数据
                    except ValueError:
                        if len(self._buffer) > self.MAX_LENGTH:
                            line, self._buffer = self._buffer, b''  #清空缓冲区
                            return self.lineLengthExceeded(line)  #传入缓冲区的数据，断开连接
                        return
                    else:
                        lineLength = len(line)
                        if lineLength > self.MAX_LENGTH:
                            exceeded = line + self.delimiter + self._buffer
                            self._buffer = b'' #清空缓冲区
                            return self.lineLengthExceeded(exceeded)
                        why = self.lineReceived(line) #进行行处理
                        if (why or self.transport and
                            self.transport.disconnecting):
                            return why
                else:
                    data = self._buffer
                    self._buffer = b''
                    why = self.rawDataReceived(data)
                    if why:
                        return why
        finally:
            self._busyReceiving = False


    def setLineMode(self, extra=b''):
        """
        Sets the line-mode of this receiver.

        If you are calling this from a rawDataReceived callback,
        you can pass in extra unhandled data, and that data will
        be parsed for lines.  Further data received will be sent
        to lineReceived rather than rawDataReceived.

        Do not pass extra data if calling this function from
        within a lineReceived callback.
        """
        self.line_mode = 1
        if extra:
            return self.dataReceived(extra)


    def setRawMode(self):
        """
        Sets the raw mode of this receiver.
        Further data received will be sent to rawDataReceived rather
        than lineReceived.
        """
        self.line_mode = 0


    def rawDataReceived(self, data):
        """
        Override this for when raw data is received.
        """
        raise NotImplementedError


    def lineReceived(self, line):
        """
        Override this for when each line is received.

        @param line: The line which was received with the delimiter removed.
        @type line: C{bytes}
        对于子类要实现该方法,当接受一行的时候,进行的一些业务处理
        """
        raise NotImplementedError


    def sendLine(self, line):
        """
        Sends a line to the other end of the connection.

        @param line: The line to send, not including the delimiter.
        @type line: C{bytes}
        将要发送的消息，不包括行结束符号，内部实现逻辑是transport.write,
        在此处对消息进行了协议的简单封装，以行的形式发送
        """
        return self.transport.write(line + self.delimiter)


    def lineLengthExceeded(self, line):
        """
        Called when the maximum line length has been reached.
        Override if it needs to be dealt with in some special way.

        The argument 'line' contains the remainder of the buffer, starting
        with (at least some part) of the line which is too long. This may
        be more than one line, or may be only the initial portion of the
        line.
        """
        return self.transport.loseConnection()